# -*- coding: utf-8 -*-
#
# Copyright 2007-2013 Luciano Xumerle. All rights reserved.
# Luciano Xumerle <luciano.xumerle@gmail.com>
#
# This file is part of cnxrename.
#
# Cnxrename is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Cnxrename is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with cnxrename.  If not, see <http://www.gnu.org/licenses/>.
#

import re
import string
import os
import urllib
import XFile
import CDDB
from optparse import OptionParser

class Renamer:

	listXFiles=[]

	startDir='.'
	sys_argv=[]

	caseInsensitive=False
	globalReplace=False

	statusOK=True

	""" parameters results """
	args=None
	options=None

	"""Audio File Extension"""
	FILEEXTENSION = '\.(mp3|wma|ogg|wav|mp2|flac|ape|shn|m4a|wv|ac3|avi)$'

	def __init__( self, path, argument ):
		self.startDir=path
		self.sys_argv=argument


	def setStatus( self, status):
		"""Sets the status of the object"""
		self.statusOK=status


	def getStatus( self ):
		"""Gets the status of the object"""
		return self.statusOK


	def replaceString( self, srcRegex, dest, caseInsensitive, globalReplace):
		"""
		Replaces the srcRegex string with destRegex string.
		"""
		count=1
		if globalReplace:
			count=0
		rr = re.compile(srcRegex, re.IGNORECASE)
		for i in range(len(self.listXFiles)):
			self.listXFiles[i].setDest(rr.sub(dest, self.listXFiles[i].getDest(), count))


	def capitalize( self ):
		"""
		Capitalize words
		"""
		for i in range(len(self.listXFiles)):
			self.listXFiles[i].setDest(toCapitalize(self.listXFiles[i].getDest()))


	def toLowerCase( self ):
		"""
		Sets string to lower case
		"""
		for i in range(len(self.listXFiles)):
			self.listXFiles[i].setDest(self.listXFiles[i].getDest().lower())


	def toUpperCase( self ):
		"""
		Sets string to lower case
		"""
		for i in range(len(self.listXFiles)):
			self.listXFiles[i].setDest(self.listXFiles[i].getDest().upper())


	def rename2safeMode( self ):
		"""
		Converts camel_case_versus_c to Camel_Case_Versus_C and removes
		every non iso character.
		"""
		self.rename2safeModeAndSpaces()
		for i in range(len(self.listXFiles)):
			self.listXFiles[i].setDest(self.listXFiles[i].getDest().replace( " ", "_" ))


	def rename2safeModeAndSpaces( self ):
		"""
		Converts camel-case_versus_c to Camel-Case Versus C
		(renames with 'rename2safeMode' and replaces underscore with space)
		"""
		for f in range(len(self.listXFiles)):
			dest = urllib.unquote( self.listXFiles[f].getDest() )
			dest = replaceCommonString( dest )
			dest = replaceAccentedString( dest )
			if not self.options.keepApostrophe:
				dest = removeApostrophe( dest )
			dest = toCapitalized( dest )
			rr = re.compile('\s*-+\s*', re.IGNORECASE)
			aa = rr.split(dest)
			for i in range(len(aa)):
				tt = re.split( '\s+', aa[ i ] )
				for j in range(len(tt)):
					tt[ j ] = replaceFixedString( tt[ j ] )
					tt[ j ] = replaceRomanNumber( tt[ j ] )
				if len(tt)<2:
					aa[ i ]=tt[0]
				else:
					aa[ i ] = " ".join ( tt )
			if len(aa)<2:
				dest=aa[0]
			else:
				dest = "-".join( aa )
			self.listXFiles[f].setDest(dest.strip(" "))


	def rename2safeModeAndSpaces2( self ):
		"""
		Converts camel-case_versus_c to Camel - Case Versus C
		(renames with 'rename2safeMode', replaces underscore with space
		and replaces '-' with ' - ')
		"""
		self.rename2safeModeAndSpaces()
		for i in range(len(self.listXFiles)):
			self.listXFiles[i].setDest(self.listXFiles[i].getDest().replace( "-", " - " ))
			self.listXFiles[i].setDest(re.sub( r'(?<=\d\d\d\d)\s*-\s*(?=\d\d\d\d)', '-', self.listXFiles[i].getDest() ))


	def dummy_o3( self ):
		"""
		Converts camel-case_versus c (1998) to Camel - Case Versus C (1998)
		"""
		for f in range(len(self.listXFiles)):
			dest = urllib.unquote( self.listXFiles[f].getDest() )
			rr = re.compile('\s*-+\s*', re.IGNORECASE)
			aa = rr.split(dest)
			for i in range(len(aa)):
				tt = re.split( '[\s_]+', aa[ i ] )
				for j in range(len(tt)):
					tt[ j ] = replaceFixedString( tt[ j ] )
					tt[ j ] = replaceRomanNumber( tt[ j ] )
				if len(tt)==1:
					aa[ i ]=tt[0]
				else:
					aa[ i ] = " ".join ( tt )
			if len(aa)==1:
				dest=aa[0]
			else:
				dest = " - ".join( aa )
			dest=re.sub( r'(?<=\d\d\d\d)\s*-\s*(?=\d\d\d\d)', '-', dest )
			self.listXFiles[f].setDest(dest.strip(" "))


	def removeUnderscore( self ):
		"""
		Converts camel-case_versus_c to Camel-CaseVersusC
		(renames with 'rename2safeMode' and removes underscore)
		"""
		self.rename2safeModeAndSpaces()
		for i in range(len(self.listXFiles)):
			self.listXFiles[i].setDest(self.listXFiles[i].getDest().replace( " ", "" ))


	def addUnderscore( self ):
		"""
		Converts camelCaseVersusC to camel_case_versus_c
		"""
		for f in range(len(self.listXFiles)):
			str=self.listXFiles[f].getDest()
			tmp = str[ 0 ]
			str=str[1:]
			for  i in range(len(str)):
				if str[ i ].isupper():
					tmp += "_" + str[ i ].lower()
				else:
					tmp += str[ i ]
				self.listXFiles[f].setDest(tmp)


	def rename2sequencedName ( self, pattern ):
		"""
		Destination name is a string like 'STRING-##.ext'
		(## is an incremented number)
		"""
		for i in range(len(self.listXFiles)):
			number=i+1
			dest=""
			if number > 9:
				dest = str( number )
			else:
				dest = "0" + str( number )
			tt=pattern
			self.listXFiles[i].setDest(tt.replace( "##", dest, 1 ))


	def replaceChar ( self, param ):
		"""
		Replace the char at position N with the string
		"""
		sep = param.find( "-" )
		if sep == -1:
			return
		p1 = int( param[ 0:sep ] ) - 1
		p2 = param[ sep + 1: ]
		for i in range(len(self.listXFiles)):
			dest = self.listXFiles[i].getDest()
			self.listXFiles[i].setDest( dest[ 0:p1 ] + p2 + dest[ p1 + 1: ] )


	def swapPosition ( self, pos ):
		"""
		Converts camel-case_versus_c to case_versus_c-camel
		"""
		sep = pos.find( "-" )
		if sep == -1:
			return
		p1 = int( pos[ 0:sep ] ) - 1
		p2 = int( pos[ sep + 1: ] ) - 1

		for i in range(len(self.listXFiles)):
			dest = self.listXFiles[i].getDest()
			# SWAP POSITION
			rr=re.compile ( "-", re.IGNORECASE )
			temp = rr.split( dest )
			if len(temp) > p1 and len(temp) > p2:
				a = temp[ p2 ]
				temp[ p2 ] = temp[ p1 ]
				temp[ p1 ] = a
			self.listXFiles[i].setDest( "-".join ( temp ) )


	def addPrefix( self, str ):
		"""
		Adds the given string as prefix
		"""
		if len(str)>0:
			for i in range(len(self.listXFiles)):
				self.listXFiles[i].setDest( str + self.listXFiles[i].getDest() )


	def addSuffix( self, str ):
		"""
		Adds the given string as suffix
		"""
		if len(str)>0:
			for i in range(len(self.listXFiles)):
				self.listXFiles[i].setDest( self.listXFiles[i].getDest() + str )


	def newExtension( self, newExt ):
		"""
		Replaces the old extension with the new.
		"""
		if len(newExt)>0:
			for i in range(len(self.listXFiles)):
				self.listXFiles[i].setExtension( newExt )


	def fromCDDB( self, txt, printAuthor ):
		"""
		Loads destination name from a <CDDB_file>.
		Returns True if all OK
		"""
		cddb = CDDB.CDDB( txt, printAuthor )
		if cddb.getSongNumber() == len(self.listXFiles):
			for i in range(len(self.listXFiles)):
				self.listXFiles[i].setDest( cddb.getDestination(i+1) )
			return True
		print "ERROR in CDDB:\n"
		print "Titles in file: " + str(cddb.getSongNumber())
		print "    Audio file: " + str(len(self.listXFiles))
		return False


	def getXFilesList( self ):
		"""
		Return an array with the current list of XFile objects.
		"""
		return self.listXFiles


	def getNumberOfFiles( self ):
		"""
		Returns teh number of files stored in the object
		"""
		return len(self.listXFiles)


	def renameFile( self, position ):
		"""
		Renames the file at given position
		"""
		return self.listXFiles[ position -1 ].renameFile()


	def executeRenameAll( self ):
		"""
		Renames all files
		"""
		for i in range(len(self.listXFiles)):
			self.renameFile( i+1 )


	def doCUE( self, txt ):
		"""Prints out the cue file using file in list"""
		# read the txt
		cddb = CDDB.CDDB( txt, False )
		self.setStatus( cddb.printCUE(self.listXFiles) )


	def doTAG( self, txt ):
		"""TAG the mp3 and ogg files using file in list"""
		# read the txt
		cddb = CDDB.CDDB( txt, False )
		self.setStatus( cddb.tagger(self.listXFiles) )


	def doM3Uopt( self, m3u ):
		self.listXFiles=[]
		fout = open(m3u, "a")
		counter = 1
		for line in open(m3u, "r"):
			process = line.lstrip().rstrip()
			if process == "" or process[0] == '#':
				continue
			if os.path.isfile(process):
				xfile = XFile.XFile(process, False, 0)
				prefixed = str(counter) + '-' + xfile.getDest()
				if counter < 10:
					prefixed = "0" + prefixed
				xfile.setDest(prefixed)
				self.listXFiles.append(xfile)
			counter+=1
		return


	def doTest( self, lnt ):
		"""
		Tests the length of the files.
		Returns the list of files with length > lnt.
		"""
		fileBAD = []
		for i in range(len(self.listXFiles)):
			name = self.listXFiles[ i ].getDest() + self.listXFiles[ i ].getExtension()
			ll = len(name)
			if ll > lnt:
				fileBAD.append(name)
		return fileBAD


	def updateCUE( self, cuefile ):
		"""Update <CUE> using all wav in current directory"""
                files=[]
		for filename in os.listdir('.'):
			if ".wav" in filename:
				files.append(filename)
		cue=[]
		count=0
		fout = open(cuefile, "a")
		for line in open(cuefile, "r"):
			line=line.rstrip()
			cue.append(line)
			if "FILE " in line:
				count=count+1

		if len(files) == count:
			count=0
                        files.sort()
			for line in cue:
				if "FILE " in line:
					print "FILE \"" + files[count] + "\" WAVE"
					count=count+1
				else:
					print line


	def parseParameters( self ):
		"""Parse Args"""
		parser = OptionParser()

		parser.add_option("--auto", action="store_true", dest="auto", help="Automatic rename. No 'yes' required")
		parser.add_option("--test", action="store_true", dest="test", help="test mode: show only the new filenames")
		parser.add_option("-q", default=True, action="store_false", dest="verbose", help="Quiet. No verbose")
		parser.add_option("-v", default=True, action="store_true", dest="verbose", help="More verbose")
		parser.add_option("-t", default=False, action="store_true", dest="fileLength", help="Check file length<64")
		parser.add_option("--t103", default=False, action="store_true", dest="fileLength103", help="Check file length<103")

		parser.add_option("--rd",  action="store_true", dest="recursive", help="Recursive directory")
		parser.add_option("--ci", default=False, action="store_true", dest="caseInsensitive", help="Match case insensitive")
		parser.add_option("-g", default=False, action="store_true", dest="allMatches", help="Subs all matched string in file")
		parser.add_option("-f", default=False, action="store_true", dest="fileOnly", help="Rename only files (skip directory)")
		parser.add_option("--64", default=False, action="store_true", dest="dest64", help="64 is the max destination file length")
		parser.add_option("--103", default=False, action="store_true", dest="dest103", help="103 is the max destination file length")

		parser.add_option("-m", default="", action="store", type="string", dest="match", help="Match with <par>")
		parser.add_option("--nm", default="", action="store", type="string", dest="noMatch", help="Skip match with <par>")

		parser.add_option("--dummy", default=False, action="store_true", dest="dummy", help="Rename in dummy mode (only replace)")
		parser.add_option("--lc", default=False, action="store_true", dest="lowerCase", help="Rename all lower case")
		parser.add_option("--uc", default=False, action="store_true", dest="upperCase", help="Rename all upper case")
		parser.add_option("--cp", default=False, action="store_true", dest="capitalize", help="Rename with capitalized word")
		parser.add_option("--o1", default=False, action="store_true", dest="to1", help="Rename with MY format (default)")
		parser.add_option("--o2", default=False, action="store_true", dest="to2", help="Rename with space (_ to space)")
		parser.add_option("--o3", default=False, action="store_true", dest="to3", help="Rename with space")
		parser.add_option("--o4", default=False, action="store_true", dest="to4", help="Rename without space (foo_bar becomes FooBar)")
		parser.add_option("--o5", default=False, action="store_true", dest="to5", help="dummy + o3 options (_ to space)")
		parser.add_option("-u", default=False, action="store_true", dest="addSpace", help="Add underscore before upper case chars")

		parser.add_option("--rp", action="store", type="string", dest="swapPosition", help="Swap position <n-m>")
		parser.add_option("--ps", action="store", type="string", dest="replacePosition", help="Replace position with a string: <n-str>")
		parser.add_option("--ai", action="store", type="string", dest="autoIncrement", help="Make numbered filename <name-##-name.ext>")
		parser.add_option("--pf", action="store", type="string", dest="prefix", help="Add a prefix to filename")
		parser.add_option("--sf", action="store", type="string", dest="suffix", help="Add a suffix to filename")
		parser.add_option("--ne", action="store", type="string", dest="newExtension", help="Change filename extension <newExt>")
		parser.add_option("--ka", default=False, action="store_true", dest="keepApostrophe", help="Do not remove the apostrophe from filename")

		parser.add_option("--txt", action="store", type="string", dest="filetxt", help="load dest name from <CDDB_like_txt_file>")
		parser.add_option("--na", default=False, action="store_true", dest="skipAuthor", help="Skip author in filename with 'txt' option")
		parser.add_option("--m3u", action="store", type="string", dest="m3u", help="load file order from <m3u_file> and add track number as prefix")
		parser.add_option("--cue", action="store", type="string", dest="cue", help="create the CUE file using <CDDB_like_txt_file> and wav files in the current directory")
		parser.add_option("--updateCUE", action="store", type="string", dest="upcue", help="Update <CUE> using all wav in current directory")
		parser.add_option("--tag", action="store", type="string", dest="tag", help="tag the files using <CDDB_like_txt_file> and MP3 files in the current directory")

		arguments=[]
		for i in range(len(self.sys_argv)):
			if len(self.sys_argv[i])>2 and self.sys_argv[i][0] == '-' and not self.sys_argv[i][1] == '-':
				arguments.append('-'+self.sys_argv[i])
			else:
				arguments.append(self.sys_argv[i])
		self.sys_argv=arguments
		(self.options, self.args) = parser.parse_args(self.sys_argv)
		if len(self.args)>2:
			return False
		return True


	def applyParameters(self):
		"""
		Sets the destination filename using the given parameters.
		Returns an array with XFile objects to rename.
		"""

		# set the max destination file length
		fileLength=0
		if self.options.dest64:
			fileLength=64
		if self.options.dest103:
			fileLength=103

		# set extension filter
		extension=""
		if self.options.cue or self.options.upcue:
			extension='\.wav$'
		elif self.options.tag:
			extension='\.(mp3|ogg)$'
		elif self.options.filetxt:
			extension=self.FILEEXTENSION
			self.options.fileOnly=True

		# set the extension regex
		extensionre=re.compile(extension + "$", re.IGNORECASE)

		# parse the directory
		files=fileList( self.startDir, self.options.recursive )

		# apply match and not match parameters
		mmm=len(self.options.match)>0
		nnn=len(self.options.noMatch)>0
		if mmm:
			keep=re.compile(self.options.match)
		if nnn:
			skip=re.compile(self.options.noMatch)

		# create the list of XFile object to be used
		for i in range(len(files)):
			xfile=XFile.XFile(files[i], os.path.isdir(files[i]), fileLength)
			if self.options.fileOnly and xfile.isDirectory():
				continue
			if nnn and skip.search( xfile.getFile() ):
                                continue
                        if mmm and not keep.search( xfile.getFile() ):
                                continue
			if not extension=="" and not extensionre.search( xfile.getExtension() ):
				continue
			self.listXFiles.append(xfile)

		# apply parameters
	        if self.options.cue and os.path.isfile(self.options.cue):
			self.doCUE( self.options.cue )
			return []

	        elif self.options.upcue and os.path.isfile(self.options.upcue):
			self.updateCUE( self.options.upcue )
			return []

	        elif self.options.tag and os.path.isfile(self.options.tag):
			self.doTAG( self.options.tag )
			return []

		elif self.options.m3u and os.path.isfile(self.options.m3u):
			self.doM3Uopt( self.options.m3u )
		else:
			if self.options.filetxt and os.path.isfile(self.options.filetxt):
				if not self.fromCDDB( self.options.filetxt, not self.options.skipAuthor ):
					self.setStatus( False )
					return []

			## search & replace if needed
			if len(self.args)>0:
				aa=self.args[0]
				bb=""
				if len(self.args)==2:
					bb=self.args[1]
				self.replaceString( aa, bb, self.options.caseInsensitive, self.options.allMatches )

			## -u
			if self.options.addSpace:
				self.addUnderscore()

			## -rp
			if self.options.swapPosition and len(self.options.swapPosition)>0:
				self.swapPosition(self.options.swapPosition)

			## -ps
			if self.options.replacePosition and len(self.options.replacePosition)>0:
					self.replaceChar ( self.options.replacePosition )

			## -ai
			if self.options.autoIncrement and self.options.autoIncrement.find( "##" )>-1:
				self.rename2sequencedName( self.options.autoIncrement )

			## -pf
			if self.options.prefix and len(self.options.prefix)>0:
				self.addPrefix(self.options.prefix)

			## -sf
			if self.options.suffix and len(self.options.suffix)>0:
				self.addSuffix(self.options.suffix)

			## -ne
			if self.options.newExtension and len(self.options.newExtension)>0:
				self.newExtension(self.options.newExtension)

			## OPTIONS -cp and -o* (-o1 is default)
			if not self.options.dummy:
				if self.options.capitalize:
					self.capitalize()
				elif self.options.to2:
					self.rename2safeModeAndSpaces()
				elif self.options.to3:
					self.rename2safeModeAndSpaces2()
				elif self.options.to4:
					self.removeUnderscore()
				elif self.options.to5:
					self.dummy_o3()
				else:
					self.rename2safeMode()

			if self.options.lowerCase:
				self.toLowerCase()
			elif self.options.upperCase:
				self.toUpperCase()

		## select list of files to be renamed
		torename=[]
		for i in range(len(self.listXFiles)):
			if self.listXFiles[i].toBeRenamed():
				torename.append(self.listXFiles[i])
		return torename


	def getOptions( self ):
		"""Returns the options object created by optparse."""
		return self.options


### NO CLASS METHOD ### NO CLASS METHOD ### NO CLASS METHOD ###
### NO CLASS METHOD ### NO CLASS METHOD ### NO CLASS METHOD ###
### NO CLASS METHOD ### NO CLASS METHOD ### NO CLASS METHOD ###

def fileList( path, recursive ):
	"""process all files in the folder"""
	files=[]
	dirs=[]
	for f in os.listdir(path):
		file = path + os.sep + f
		if os.path.isdir(file):
			dirs.append(file)
		else:
			files.append(file)
	files.sort()
	if len(dirs)>0:
		dirs.sort()
		for i in range(len(dirs)):
			if recursive:
				files.extend( fileList(dirs[ i ], recursive) )
			files.append(dirs[ i ])
	return files


def toCapitalized( line ):
	"""
	Capitalize words in a line.
	"""
	str=line.strip()
	dest=""
	if len(str) == 0:
		return ""
	if str[0].isalpha():
		dest += str[ 0 ].upper()
	else:
		dest += str[ 0 ]
	for i in range(1, len(str)):
		if str[ i ].isalpha():
			dotted=str[ i-1 ] == '.' and len(str) > ( i + 1 ) and str[ i + 1 ] == '.'
			if not str[ i - 1].isalpha() or dotted:
				dest += str[ i ].upper()
			else:
				dest += str[ i ].lower()
		else:
			dest += str[ i ]
	return dest


def replaceFixedString( src ):
	"""
	Replaces some common string
	"""
	selfCaseWord = [
		["^ost$", "OST"],
		["^xfree$", "XFree"],
		["^ms$", "MS"],
		["^cdr", "CDR"],
		["^cd", "CD"],
		["^ep", "EP"],
		["^lp", "LP"],
		["^divx$", "DivX"],
		["^dvd$", "DVD"],
		["^tv$", "TV"],
		["^vhs$", "VHS"],
		["^id$", "ID"],
		["^dj$", "DJ"],
		["^usa$", "USA"],
		["^us$", "US"],
		["^uk$", "UK"],
		["^vv\\.aa\\.$", "AA.VV."],
		["^aa\\.vv\\.$", "AA.VV."]
	]

	tt = src
	for j in range(len(selfCaseWord)):
		tt = re.compile( selfCaseWord[ j ][ 0 ], re.I ).sub( selfCaseWord[ j ][ 1 ], tt )
	return tt


def replaceAccentedString( src ):
	"""
	Replaces non standard ascii chars with ascii chars.
	"""
	isoCharArray = [
		# LETTER E
		["É", "e'"],
		["È", "e'"],
		["è", "e'"],
		["é", "e'"],
		["ê", "e"],
		["Ê", "e"],
		["ë", "e"],
		["Ë", "e"],
		# LETTER O
		["ó", "o'"],
		["ò", "o'"],
		["Ò", "o'"],
		["Ó", "o'"],
		["Ö", "o"],
		["ö", "o"],
		["Ô", "o"],
		["ô", "o"],
		["Õ", "o"],
		["õ", "o"],
		# LETTER I
		["Ì", "i'"],
		["Í", "i'"],
		["ì", "i'"],
		["í", "i'"],
		["î", "i"],
		["Î", "i"],
		["ï", "i"],
		["Ï", "i"],
		# LETTER U
		["Ù", "u'"],
		["Ú", "u'"],
		["ù", "u'"],
		["ú", "u'"],
		["û", "u"],
		["Û", "u"],
		["ü", "u"],
		["Ü", "u"],
		# LETTER A
		# utf8 with à has problem. Use exadecimal values \xc3\xa0
		# \xa0 is no breaked space. \xc3 is Ã
		['\xc3', "a"],
		['\xa0', ""],
		["à", "a"],
		["á", "a"],
		["À", "a"],
		["Á", "a"],
		["Â", "a"],
		["â", "a"],
		["Ä", "a"],
		["ä", "a"],
		["å", "a"],
		["ã", "a"],
		["Ã", "a"],
		# OTHER ISO
		["Ð", "d"],
		["ð", "d"],
		["Æ", "ae"],
		["æ", "ae"],
		["Þ", "t"],        # LATIN CAPITAL LETTER THORN
		["þ", "t"],        # LATIN SMALL LETTER THORN
		["Ñ", "n"],
		["ñ", "n"],
		["ß", "s"],        # LATIN SMALL LETTER SHARP S
		["Ý", "y'"],
		["ý", "y'"],
		["ÿ", "y"],
		["Ç", "c"],
		["ç", "c"],
		["ø", "o"],
		["Ø", "o"],
		[ "×", "x" ]
	]
	tt = src
	for j in range(len(isoCharArray)):
		tt = tt.replace( isoCharArray[ j ][ 0 ], isoCharArray[ j ][ 1 ] )
	return tt


def replaceCommonString( str ):
	"""
	Replace parenthesis, dots & othes non standards chars.
	"""
	symbolCharArray = [
		[ "_", " " ],
		[ '\xa0', " " ],
		# parenthesis
		[ "(", "-" ],
		[ ")", "-" ],
		[ "[", "-" ],
		[ "]", "-" ],
		[ "{", "-" ],
		[ "}", "-" ],
		[ "<", "-" ],
		[ ">", "-" ],
		[ "«", "-" ],
		[ "»", "-" ],
		# dots
		["`", "'"],
		[ ":", "-" ],
		[ ";", "-" ],
		[ "?", " " ],
		["¿", " "],
		[ "!", " " ],
		["¡", " "],
		[",", " "],
		["·", " "],
		[ "\\", " + " ],
		[ "/", " + " ],
		[ "&", " + " ],
		[ "@", " " ],
		[ "#", " " ],
		[ "~", " " ],
		[ "*", " " ],
		[ "%", " " ],
		[ "\"", " " ],
		[ "°", " " ],
		[ "©", " " ],
		[ "®", " " ]
	]

	# remove sequences
	ss = [
		[ '\.+', "." ],
		[ '[_\s\-]*\++[\-\s_]*', " + " ],
		[ '\s*\-+[\s\-_]*', "-" ],
		[ '[\s_\-+]+$', "" ],
		[ '^[\s_\-+]+', "" ]
	]

	tt=str

	for j in range(len(symbolCharArray)):
		tt = tt.replace( symbolCharArray[ j ][ 0 ], symbolCharArray[ j ][ 1 ] )

	for j in range(len(ss)):
		tt = re.compile( ss[ j ][ 0 ] ).sub( ss[ j ][ 1 ], tt )
	return tt


def replaceRomanNumber( src ):
	"""
	Sets a roman number string to uppercase.
	"""
	romanNumbers = [
		"I",
		"II",
		"III",
		"IV",
		"V",
		"VI",
		"VII",
		"VIII",
		"IX",
		"X",
		"XI",
		"XII",
		"XIII",
		"XIV",
		"XV",
		"XVI",
		"XVII",
		"XVIII",
		"XIX",
		"XX"
	]
	for i in range(len( romanNumbers )):
		if re.compile( "^" + romanNumbers[ i ] + "$", re.IGNORECASE ).search(src):
			return romanNumbers[ i ]
		if re.compile( "^" + romanNumbers[ i ] + "\.$", re.IGNORECASE ).search(src):
			return romanNumbers[ i ]+'.'
	return src


def removeApostrophe( str ):
	"""
	Remove the apostrophe character from destination namefile.
	"""
	return str.replace( "'", "" )

